package com.jdd.modules.parkcar.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.andyczy.java.excel.ExcelUtils;
import com.jdd.common.api.vo.Result;
import com.jdd.common.aspect.annotation.*;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.system.vo.LoginUser;
import com.jdd.common.util.*;
import com.jdd.common.util.excel.entity.params.ExportParams;
import com.jdd.common.util.excel.entity.params.ImportParams;
import com.jdd.common.util.excel.util.ExcelImportUtil;
import com.jdd.common.util.excel.web.entity.vo.NormalExcelConstants;
import com.jdd.common.util.excel.web.view.EasypoiSingleExcelView;
import com.jdd.modules.configcartype.entity.ConfigCarType;
import com.jdd.modules.configcartype.service.IConfigCarTypeService;
import com.jdd.modules.parkcar.entity.BlackAndWhiteImportResult;
import com.jdd.modules.parkcar.entity.ParkBlackAndWhiteForeverImport;
import com.jdd.modules.parkcar.entity.ParkBlackAndWhiteImport;
import com.jdd.modules.parkcar.entity.ParkBlackList;
import com.jdd.modules.parkcar.service.IParkBlackListService;
import com.jdd.modules.parking.entity.ConfigParkInfo;
import com.jdd.modules.parking.entity.ParkInfo;
import com.jdd.modules.parking.service.IConfigParkInfoService;
import com.jdd.modules.parking.service.IParkInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * @Description: 黑名单
 * @author: dongshuang
 * @date: 2021年03月06日 15:27
 */
@Slf4j
@Api(tags = "黑名单")
@RestController
@RequestMapping("/blacklist/parkBlackList")
public class ParkBlackListController {
    @Resource
    private IParkBlackListService parkBlackListService;

    @Resource
    private IParkInfoService parkInfoService;

    @Resource
    private IConfigCarTypeService configCarTypeService;

    @Resource
    private ExecutorService executorService;

    @Resource
    private IConfigParkInfoService configParkInfoService;

    /**
     * 分页查询
     *
     * @param parkBlackList
     * @param pageNo
     * @param pageSize
     * @param startTime2
     * @param endTime2
     * @param req
     * @return
     */
    @AutoLog(value = "黑名单-分页列表查询")
    @ApiOperation(value = "黑名单-分页列表查询", notes = "黑名单-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<ParkBlackList>> queryPageList(ParkBlackList parkBlackList,
                                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                      String startTime2, String endTime2,
                                                      HttpServletRequest req) {
        Result<IPage<ParkBlackList>> result = new Result<IPage<ParkBlackList>>();
        QueryWrapper<ParkBlackList> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(parkBlackList.getIsForever())) {
            queryWrapper.eq("is_forever", parkBlackList.getIsForever());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getPlateNo())) {
            queryWrapper.like("plate_no", parkBlackList.getPlateNo());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getStartTime())) {
            queryWrapper.ge("create_time", parkBlackList.getStartTime());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getEndTime())) {
            queryWrapper.le("create_time", parkBlackList.getEndTime());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getUserName())) {
            queryWrapper.like("user_name", parkBlackList.getUserName());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getMobile())) {
            queryWrapper.like("mobile", parkBlackList.getMobile());
        }
        queryWrapper.orderByDesc("create_time");
        queryWrapper.eq("license_type", 2);

        if (StringUtils.isNotBlank(startTime2) && StringUtils.isNotBlank(endTime2)) {
            queryWrapper.and(wrapper -> wrapper.ge("create_time", startTime2 + " 00:00:00").le("create_time", endTime2 + " 23:59:59"));
        }
        Page<ParkBlackList> page = new Page<ParkBlackList>(pageNo, pageSize);
        IPage<ParkBlackList> pageList = parkBlackListService.page(page, queryWrapper);
        result.setSuccess(true);
        result.setResult(pageList);
        return result;
    }

    /**
     * 返回当前用户具有权限的车场
     *
     * @param
     * @return
     */
    @AutoLog(value = "黑名单车厂选择-查询当前用户具有权限的车场集合")
    @ApiOperation(value = "黑名单车厂选择-查询当前用户具有权限的车场集合", notes = "黑名单车厂选择-查询当前用户具有权限的车场集合")
    @GetMapping(value = "/queryParkList")
    public Result<List<ParkInfo>> queryParkList() {

        Result<List<ParkInfo>> result = new Result<>();
        QueryWrapper<ParkInfo> queryWrapper = new QueryWrapper<>();
        List<ParkInfo> parkList = parkInfoService.list(queryWrapper);
        result.setResult(parkList);
        result.setSuccess(true);
        return result;
    }

    /**
     * 黑名单-详情-月租车类型
     *
     * @param map
     * @return
     */
    @AutoLog(value = "黑名单-详情-月租车类型")
    @ApiOperation(value = "黑名单-详情-月租车类型", notes = "黑名单-详情-月租车类型")
    @PostMapping(value = "/carTypeInfo")
    public Result<ConfigCarType> getCarTypeInfo(@RequestBody Map<String, String> map
    ) {
        String carTypeId = map.get("carTypeId");
        Result<ConfigCarType> result = new Result<ConfigCarType>();

        QueryWrapper<ConfigCarType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", carTypeId);
        ConfigCarType configCarType = configCarTypeService.getOne(queryWrapper);

        result.setResult(configCarType);
        result.setSuccess(true);
        return result;
    }

    /**
     * 添加
     *
     * @param parkBlackList
     * @return
     */
    @AutoLog(value = "黑名单-添加")
    @ApiOperation(value = "黑名单-添加", notes = "黑名单-添加")
    @PostMapping(value = "/add")
    @OperationLogDetail(detail = "黑名单添加", level = LogLevelType.ONE, operationType = OperationType.INSERT, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkBlackList> add(@RequestBody ParkBlackList parkBlackList) {
        Result<ParkBlackList> result = new Result<ParkBlackList>();
        try {
            LoginUser loginUser = LoginUserUtils.getLoginUser();
            ConfigParkInfo configParkInfo = configParkInfoService.findConfigParkInfoByParkCode();
            if (ObjectUtil.isNull(configParkInfo)) {
                return Result.error(510, "车辆信息配置为空，请检查");
            }
            if (!PlateNoCheckUtil.checkPlateNo(parkBlackList.getPlateNo())) {
                return Result.error(510, "车牌号错误");
            }
            parkBlackList.setParkCode(configParkInfo.getParkCode());
            LambdaQueryWrapper<ParkBlackList> parkBlackListQueryWrapper = new LambdaQueryWrapper<>();
            parkBlackListQueryWrapper.eq(ParkBlackList::getParkCode, parkBlackList.getParkCode());
            parkBlackListQueryWrapper.eq(ParkBlackList::getPlateNo, parkBlackList.getPlateNo());
            List<ParkBlackList> list = parkBlackListService.list(parkBlackListQueryWrapper);
            if (list.size() > 0) {
                for (int index = 0; index < list.size(); index++) {
                    if (list.get(index).getLicenseType() == 1) {
                        return Result.error("该车牌号已被设置为白名单，如需添加到黑名单请先删除该车的白名单记录");
                    }
                    if (list.get(index).getLicenseType() == 3) {
                        return Result.error("该车牌号已被设置为储值车，如需添加到黑名单请先删除该车的储值车记录");
                    }
                    if (list.get(index).getLicenseType() == 2) {
                        return Result.error("该车牌号已经在黑名单里了");
                    }
                }
            }
            QueryWrapper<ParkInfo> queryWrapper = new QueryWrapper<ParkInfo>();
            ParkInfo parkInfo = parkInfoService.getOne(queryWrapper);
            parkBlackList.setParkName(parkInfo.getParkName());
            parkBlackList.setId(SnowFlakeUtil.getId());
            parkBlackList.setCreateUser(loginUser.getUsername());
            parkBlackListService.save(parkBlackList);
            result.success("添加成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("操作失败");
        }
        return result;
    }

    /**
     * 编辑
     *
     * @param parkBlackList
     * @return
     */
    @AutoLog(value = "黑名单-编辑")
    @ApiOperation(value = "黑名单-编辑", notes = "黑名单-编辑")
    @PutMapping(value = "/edit")
    @OperationLogDetail(detail = "黑名单编辑", level = LogLevelType.ONE, operationType = OperationType.UPDATE, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkBlackList> edit(@RequestBody ParkBlackList parkBlackList) {
        Result<ParkBlackList> result = new Result<ParkBlackList>();
        ParkBlackList parkBlackListEntity = parkBlackListService.getById(parkBlackList.getId());
        if (!PlateNoCheckUtil.checkPlateNo(parkBlackList.getPlateNo())) {
            return Result.error(510, "车牌号错误");
        }
        QueryWrapper<ParkBlackList> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("plate_no", parkBlackList.getPlateNo());
        queryWrapper1.ne("id", parkBlackList.getId());
        ParkBlackList parkBlackList1 = parkBlackListService.getOne(queryWrapper1);
        if (parkBlackList1 != null) {
            result.error500("车场已有该车辆");
            return result;
        }

        QueryWrapper<ParkInfo> queryWrapper = new QueryWrapper<ParkInfo>();
        ParkInfo parkInfo = parkInfoService.getOne(queryWrapper);
        parkBlackList.setParkName(parkInfo.getParkName());

        if (parkBlackListEntity == null) {
            result.error500("未找到对应实体");
        } else {
            boolean ok = parkBlackListService.updateById(parkBlackList);
            //TODO 返回false说明什么？
            if (ok) {
                result.success("修改成功!");
            }
        }
        return result;
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "黑名单-通过id删除")
    @ApiOperation(value = "黑名单-通过id删除", notes = "黑名单-通过id删除")
    @DeleteMapping(value = "/delete")
    @OperationLogDetail(detail = "黑名单通过Id删除", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        try {
            parkBlackListService.removeById(id);
        } catch (Exception e) {
            log.error("删除失败", e.getMessage());
            return Result.error("删除失败!");
        }
        return Result.ok("删除成功!");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "黑名单-通过id查询")
    @ApiOperation(value = "黑名单-通过id查询", notes = "黑名单-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<ParkBlackList> queryById(@RequestParam(name = "id", required = true) String id) {
        Result<ParkBlackList> result = new Result<ParkBlackList>();
        ParkBlackList parkBlackList = parkBlackListService.getById(id);
        if (parkBlackList == null) {
            result.error500("未找到对应实体");
        } else {
            result.setResult(parkBlackList);
            result.setSuccess(true);
        }
        return result;
    }

    /**
     * 导出excel
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, HttpServletResponse response, ParkBlackList parkBlackList) {
        // Step.1 组装查询条件
        QueryWrapper<ParkBlackList> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(parkBlackList.getIsForever())) {
            queryWrapper.eq("is_forever", parkBlackList.getIsForever());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getPlateNo())) {
            queryWrapper.like("plate_no", parkBlackList.getPlateNo());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getStartTime())) {
            queryWrapper.ge("create_time", parkBlackList.getStartTime());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getEndTime())) {
            queryWrapper.le("create_time", parkBlackList.getEndTime());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getUserName())) {
            queryWrapper.like("user_name", parkBlackList.getUserName());
        }
        if (ObjectUtil.isNotEmpty(parkBlackList.getMobile())) {
            queryWrapper.like("mobile", parkBlackList.getMobile());
        }
        queryWrapper.orderByDesc("create_time");
        queryWrapper.eq("license_type", 2);
        // Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "黑名单列表");
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("黑名单列表数据", "导出信息"));
        // 导出文件名称
        // 查询表中数据大小
        int listSize = parkBlackListService.count(queryWrapper);
        // 定义每页数量
        int pageSize = 100;
        // 定义线程列表
        List<CompletableFuture<ModelAndView>> futureList = new ArrayList<>();
        // 循环查询，每次查询一页
        for (int pageNo = 1; pageNo <= listSize / pageSize + 1; pageNo++) {
            int number = pageNo;
            // 开启线程查询
            CompletableFuture<ModelAndView> completableFuture = CompletableFuture.supplyAsync(() -> {
                return addDataToModelAndView(new ModelAndView(), queryWrapper, number, pageSize);
            }, executorService);
            futureList.add(completableFuture);
        }
        // 等待每个线程结束后
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
        List<ParkBlackList> resultList = new ArrayList<>();
        futureList.forEach(a -> {
            try {
                // 将结果添加到列表中
                resultList.addAll((List<ParkBlackList>) a.join().getModel().get(NormalExcelConstants.DATA_LIST));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 将数据添加到Excel文件内
        mv.addObject(NormalExcelConstants.CLASS, ParkBlackList.class);
        mv.addObject(NormalExcelConstants.DATA_LIST, resultList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();
            ImportParams params = ImportParams.builder().build();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<ParkBlackList> listParkBlackLists = ExcelImportUtil.importExcel(file.getInputStream(), ParkBlackList.class, params);
                parkBlackListService.saveBatch(listParkBlackLists);
                return Result.ok("文件导入成功！数据行数:" + listParkBlackLists.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.ok("文件导入失败！");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "黑名单-批量删除")
    @ApiOperation(value = "黑名单-批量删除", notes = "黑名单-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    @OperationLogDetail(detail = "黑名单批量删除", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkBlackList> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        Result<ParkBlackList> result = new Result<ParkBlackList>();
        if (ids == null || "".equals(ids.trim())) {
            result.error500("参数不识别！");
        } else {
            this.parkBlackListService.removeByIds(Arrays.asList(ids.split(",")));
            result.success("删除成功!");
        }
        return result;
    }

    private ModelAndView addDataToModelAndView(ModelAndView mv, QueryWrapper<ParkBlackList> queryWrapper, int pageNo, int pageSize) {
        Page<ParkBlackList> page = new Page<>(pageNo, pageSize);
        queryWrapper.lambda().eq(ParkBlackList::getLicenseType, 2);
        IPage<ParkBlackList> iPage = parkBlackListService.page(page, queryWrapper);
        mv.addObject(NormalExcelConstants.DATA_LIST, iPage.getRecords());
        return mv;
    }

    @AutoLog(value = "黑名单信息导入-获取车场配置信息")
    @ApiOperation(value = "黑名单信息导入-获取车场配置信息", notes = "黑名单信息导入-获取车场配置信息")
    @GetMapping(value = "/findConfigParkInfo")
    public Result<?> findConfigParkInfo(HttpServletRequest request) {
        request.getSession();
        ConfigParkInfo configParkInfo = configParkInfoService.findConfigParkInfoByParkCode();
        if (ObjectUtil.isNull(configParkInfo)) {
            return Result.error("获取车场配置信息失败！");
        } else {
            return Result.ok(configParkInfo);
        }
    }

    /**
     * 黑名单信息导入模板
     *
     * @param request   request
     * @param response  response
     * @param isForever 有效期 1：永久期限 0： 自定义时间
     * @return 模板信息
     */
    @AutoLog(value = "黑名单信息导入模板下载")
    @ApiOperation(value = "黑名单信息导入模板下载", notes = "黑名单信息导入模板下载")
    @RequestMapping(value = "/importTemplate")
    public ModelAndView importTemplate(HttpServletRequest request, HttpServletResponse response, String isForever) {
        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());

        if (JddConstant.StringNumber.STRING_ONE.equals(isForever)) {
            //永久期限模板
            mv.addObject(NormalExcelConstants.FILE_NAME, "黑名单信息(永久期限)");
            mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("黑名单信息(永久期限)", "黑名单导入模板(永久期限)"));
            mv.addObject(NormalExcelConstants.CLASS, ParkBlackAndWhiteForeverImport.class);
            List<ParkBlackAndWhiteForeverImport> list = new LinkedList<>();
            ParkBlackAndWhiteForeverImport parkBlack = new ParkBlackAndWhiteForeverImport();
            parkBlack.setPlateNo("实际车牌号");
            parkBlack.setIsForever("永久");
            parkBlack.setUserName("XX");
            parkBlack.setRemark("此行为示例数据,请参考格式填写，导入前请删除本行数据！");
            list.add(parkBlack);
            mv.addObject(NormalExcelConstants.DATA_LIST, list);
        } else {
            //自定义时间模板
            mv.addObject(NormalExcelConstants.FILE_NAME, "黑名单信息(自定义时间)");
            mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("黑名单信息(自定义时间)", "黑名单导入模板(自定义时间)"));
            mv.addObject(NormalExcelConstants.CLASS, ParkBlackAndWhiteImport.class);
            List<ParkBlackAndWhiteImport> list = new LinkedList<>();
            ParkBlackAndWhiteImport parkBlack = new ParkBlackAndWhiteImport();
            parkBlack.setPlateNo("实际车牌号");
            parkBlack.setIsForever("自定义");
            parkBlack.setStartDate("2021-01-01");
            parkBlack.setEndDate("2021-12-31");
            parkBlack.setStartTime("00:00:00");
            parkBlack.setEndTime("23:59:59");
            parkBlack.setUserName("XX");
            parkBlack.setRemark("此行为示例数据,请参考格式填写，导入前请删除本行数据！");
            list.add(parkBlack);
            mv.addObject(NormalExcelConstants.DATA_LIST, list);
        }
        return mv;
    }

    /**
     * 黑名单校验及导入进度获取
     *
     * @param request  request
     * @param response response
     * @return 进度数据
     */
    @RequestMapping(value = "/getCheckProgress", method = RequestMethod.POST)
    public Result<Integer> getCheckProgress(HttpServletRequest request, HttpServletResponse response) {
        Result<Integer> result = new Result<>();
        String currDateTime = request.getParameter("currDateTime");
        try {
            String percent = String.valueOf(request.getSession().getAttribute(currDateTime));
            if (StringUtils.isEmpty(percent) || "null".equals(percent)) {
                percent = "0";
            }
            result.setResult(Integer.parseInt(percent));
        } catch (Exception e) {
            result.setResult(0);
        }
        return result;
    }

    /**
     * 黑名单信息通过excel导入数据校验
     *
     * @param request  request
     * @param response response
     * @return 数据校验结果
     */
    @RequestMapping(value = "/importFromExcelCheck", method = RequestMethod.POST)
    public Result<List<BlackAndWhiteImportResult>> importFromExcelCheck(HttpServletRequest request, HttpServletResponse response) {
        Result<List<BlackAndWhiteImportResult>> result = new Result<>();
        //校验结果信息列表
        List<BlackAndWhiteImportResult> importResultMessageList = new LinkedList<>();
        //用于存储的格式正确的黑名单信息
        List<ParkBlackList> parkBlackList = new ArrayList<>();
        //用于存储拥有相同数据的黑名单信息
        List<ParkBlackList> sameParkBlackList = new ArrayList<>();

        // 获得上传文件的请求
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

        String isForever = multipartRequest.getParameter("isForever");
        String weekDay = multipartRequest.getParameter("weekDay");


        // 从请求中获得上传文件的集合
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        // 遍历文件集合
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            try {
                // 获得文件
                MultipartFile file = entity.getValue();
                // 得到文件名
                String fileName = file.getOriginalFilename();
                // 获得Excel文件的扩展名
                String extName = fileName.substring(fileName.lastIndexOf('.') + 1);
                //excel文件格式校验
                if (!StringUtils.equals("xls", extName) && !StringUtils.equals("xlsx", extName)) {
                    log.error("无法识别的Excel文件,请下载模板文件,进行导入!");
                    result.error500("无法识别的Excel文件,请下载模板文件,进行导入");
                    return result;
                }

                //获取Excel数据
                List<List<LinkedHashMap<String, String>>> excelLists = getExcelLists(file, extName);

                //检测导入Excel文件的大小
                Result<Object> listSizeCheckResult = importListSizeCheck(excelLists, 500);
                //如果检测不通过
                if (listSizeCheckResult.getCode() != 200) {
                    log.error(listSizeCheckResult.getMessage());
                    result.error500(listSizeCheckResult.getMessage());
                    return result;
                }

                //数据校验组装
                for (List<LinkedHashMap<String, String>> linkedHashMaps : excelLists) {
                    importResultMessageList = getNoSameDataParkCarBlack(request, linkedHashMaps, parkBlackList, sameParkBlackList, isForever, weekDay, true);
                }
                if (importResultMessageList.size() > 0) {
                    result.setResult(importResultMessageList);
                    result.setSuccess(false);
                    return result;
                }

            } catch (Exception e) {
                log.error("黑名单文件校验失败", e);
                result.error500("黑名单文件校验失败");
                return result;
            }
        }
        result.success("黑名单文件校验成功！");
        BlackAndWhiteImportResult blackAndWhiteImportResult = new BlackAndWhiteImportResult();
        blackAndWhiteImportResult.setTotalCount(parkBlackList.size());
        importResultMessageList.add(blackAndWhiteImportResult);
        result.setResult(importResultMessageList);
        result.setSuccess(true);
        return result;
    }

    /**
     * 获取Excel数据
     *
     * @param file    文件
     * @param extName 文件扩展名
     * @return 列表数据
     * @throws IOException 异常信息
     */
    private List<List<LinkedHashMap<String, String>>> getExcelLists(MultipartFile file, String extName) throws IOException {
        // 设置Excel文件的标题所在行数
        HashMap<Integer, Integer> hashMapIndex = new HashMap<>(1);
        hashMapIndex.put(1, 3);
        // 设置Excel文件单页名称
        String[] sheetNames = new String[]{"黑名单"};
        // 获得Excel文件的输入流
        InputStream inputStream = file.getInputStream();
        Workbook book = null;

        if (StringUtils.equals("xls", extName)) {
            // Excel文件为Excel2003之前的版本
            book = new HSSFWorkbook(inputStream);
        } else if (StringUtils.equals("xlsx", extName)) {
            // Excel文件的版本为Excel2007
            book = new XSSFWorkbook(inputStream);
        }
        // 初始化Excel工具类
        ExcelUtils excelUtils = ExcelUtils.initialization();
        // 设置工具类读取日期数据的格式
        excelUtils.setDateFormatStr("yyyy-MM-dd HH:mm:ss");
        excelUtils.setExpectDateFormatStr("yyyy-MM-dd HH:mm:ss");
        // 读取Excel文件
        List<List<LinkedHashMap<String, String>>> list = ExcelUtils.importForExcelData(book, sheetNames, hashMapIndex, null);
        return list;
    }

    /**
     * 黑名单信息通过excel导入数据
     *
     * @param request  request
     * @param response response
     * @return 导入结果
     */
    @RequestMapping(value = "/importFromExcel", method = RequestMethod.POST)
    public Result<List<BlackAndWhiteImportResult>> importFromExcel(HttpServletRequest request, HttpServletResponse response) {
        Result<List<BlackAndWhiteImportResult>> result = new Result<>();
        //导入结果信息列表
        List<BlackAndWhiteImportResult> importResultMessageList = new LinkedList<>();
        //用于存储的格式正确的黑名单信息
        List<ParkBlackList> parkBlackList = new ArrayList<>();
        //用于存储拥有相同数据的黑名单信息
        List<ParkBlackList> sameParkBlackList = new ArrayList<>();

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        //有效期 1：永久期限 0： 自定义时间
        String isForever = multipartRequest.getParameter("isForever");
        //导入方式 1:忽略重复(以已存在记录为准) 0:覆盖导入(以最新记录为准)
        String importType = multipartRequest.getParameter("importType");
        //指定周日
        String weekDay = multipartRequest.getParameter("weekDay");

        // 从请求中获得上传文件的集合
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        // 遍历文件集合
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            try {
                // 获得文件
                MultipartFile file = entity.getValue();
                // 得到文件名
                String fileName = file.getOriginalFilename();
                // 获得Excel文件的扩展名
                String extName = fileName.substring(fileName.lastIndexOf('.') + 1);

                //获取Excel数据
                List<List<LinkedHashMap<String, String>>> excelLists = getExcelLists(file, extName);

                //数据校验组装
                for (List<LinkedHashMap<String, String>> linkedHashMaps : excelLists) {
                    getNoSameDataParkCarBlack(request, linkedHashMaps, parkBlackList, sameParkBlackList, isForever, weekDay, false);
                }

                //数据导入
                importResultMessageList = importParkParkWhiteByList(request, parkBlackList, importType);
                if (importResultMessageList.size() > 0) {
                    result.setResult(importResultMessageList);
                    result.setSuccess(false);
                    return result;
                }
            } catch (Exception e) {
                log.error("黑名单导入失败", e);
                result.error500("黑名单导入失败");
                return result;
            }
        }
        result.success("黑名单导入成功！");
        BlackAndWhiteImportResult blackAndWhiteImportResult = new BlackAndWhiteImportResult();
        blackAndWhiteImportResult.setTotalCount(parkBlackList.size());
        importResultMessageList.add(blackAndWhiteImportResult);
        result.setResult(importResultMessageList);
        result.setSuccess(true);
        return result;
    }

    /**
     * 检测黑名单导入列表的大小
     *
     * @param list    导入数据列表
     * @param maxSize 最大数
     * @return 检测结果
     */
    private Result<Object> importListSizeCheck(List<List<LinkedHashMap<String, String>>> list, Integer maxSize) {

        // 如果列表大小不为0
        if (list.size() != 0) {
            if (list.get(0).size() > maxSize) {
                log.error("导入文件表格中的数据最大为" + maxSize + "条");
                return Result.error("导入文件表格中的数据最大为" + maxSize + "条");
            }
            if (list.get(0).size() != 0) {
                String[] arr = new String[list.get(0).get(0).size()];
                Arrays.fill(arr, "");
                String[] arr1 = new String[list.get(0).get(0).size()];
                String[] strings = list.get(0).get(0).values().toArray(arr1);
                if (Arrays.equals(arr, strings)) {
                    log.error("文件没有数据");
                    return Result.error("文件没有数据！");
                }
            } else {
                log.error("文件没有数据");
                return Result.error("文件没有数据！");
            }
        } else {
            log.error("空文件");
            return Result.error("空文件");
        }
        return Result.ok();
    }

    /**
     * 按list批量导入
     *
     * @param request    request
     * @param list       格式正确的储值车信息
     * @param importType 导入方式 1:忽略重复(以已存在记录为准) 0:覆盖导入(以最新记录为准)
     * @return 导入结果信息
     */
    private List<BlackAndWhiteImportResult> importParkParkWhiteByList(HttpServletRequest request, List<ParkBlackList> list, String importType) {
        List<BlackAndWhiteImportResult> importResultMessageList = new ArrayList<>();
        String currDateTime = request.getParameter("currDateTime");

        for (int i = 0; i < list.size(); i++) {
            ParkBlackList parkBlackInfo = list.get(i);
            try {
                // 创建一个数值格式化对象
                NumberFormat numberFormat = NumberFormat.getInstance();
                numberFormat.setMaximumFractionDigits(0);
                String result = numberFormat.format((float) i / (float) list.size() * 100);
                request.getSession().setAttribute(currDateTime, Integer.parseInt(result));

                LambdaQueryWrapper<ParkBlackList> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ParkBlackList::getPlateNo, parkBlackInfo.getPlateNo());
//                queryWrapper.eq(ParkBlackList::getLicenseType, parkBlackInfo.getLicenseType());
                ParkBlackList existParkInfo = parkBlackListService.getOne(queryWrapper);

                if (null != existParkInfo) {
                    if (JddConstant.ParkWhiteListConstant.LICENSE_TYPE_ONE.equals(String.valueOf(existParkInfo.getLicenseType()))) {
                        BlackAndWhiteImportResult message = new BlackAndWhiteImportResult();
                        message.setTotalCount(list.size());
                        message.setId(i + 3);
                        message.setPlateNo(parkBlackInfo.getPlateNo());
                        message.setUserName(parkBlackInfo.getUserName());
                        message.setMessage("该车牌号已被设置为白名单，如需添加到黑名单请先删除该车的白名单记录");
                        message.setStatus("失败");
                        importResultMessageList.add(message);
                    } else {
                        //忽略重复(以已存在记录为准)
                        if (JddConstant.StringNumber.STRING_ONE.equals(importType)) {
                            continue;
                        } else {
                            //覆盖导入(以最新记录为准)
                            parkBlackListService.removeById(existParkInfo.getId());
                            parkBlackListService.save(parkBlackInfo);
                        }
                    }
                } else {
                    parkBlackListService.save(parkBlackInfo);
                }
            } catch (Exception e) {
                BlackAndWhiteImportResult message = new BlackAndWhiteImportResult();
                message.setTotalCount(list.size());
                message.setId(i + 3);
                message.setPlateNo(parkBlackInfo.getPlateNo());
                message.setUserName(parkBlackInfo.getUserName());
                message.setMessage("导入失败" + e.getMessage());
                message.setStatus("失败");
                importResultMessageList.add(message);
            }
        }
        return importResultMessageList;
    }

    /**
     * Excel列表中数据格式自检测
     *
     * @param request        request
     * @param linkedHashMaps 导入的黑名单信息列表
     * @param noSameDataList 用于存储的格式正确的，无相同数据的储值车信息
     * @param sameDatalist   用于存储拥有相同数据的储值车信息
     * @param isForever      有效期 1：永久期限 0： 自定义时间
     * @param weekDay        指定周日
     * @param isCheck        是否为校验操作
     * @return 导入结果信息
     */
    private List<BlackAndWhiteImportResult> getNoSameDataParkCarBlack(HttpServletRequest request, List<LinkedHashMap<String, String>> linkedHashMaps, List<ParkBlackList> noSameDataList,
                                                                      List<ParkBlackList> sameDatalist, String isForever, String weekDay, boolean isCheck) {
        LoginUser loginUser = LoginUserUtils.getLoginUser();
        List<BlackAndWhiteImportResult> resultList = new ArrayList<>();
        Set<String> noSameDataPlantNoList = new HashSet<>();

        ConfigParkInfo configParkInfo = configParkInfoService.findConfigParkInfoByParkCode();
        String currDateTime = request.getParameter("currDateTime");

        for (int index = 0; index < linkedHashMaps.size(); index++) {
            if (isCheck) {
                // 创建一个数值格式化对象
                NumberFormat numberFormat = NumberFormat.getInstance();
                numberFormat.setMaximumFractionDigits(0);
                String result = numberFormat.format((float) index / (float) linkedHashMaps.size() * 100);
                request.getSession().setAttribute(currDateTime, Integer.parseInt(result));
            }
            ParkBlackList parkBlackInfo = new ParkBlackList();
            LinkedHashMap<String, String> linkedHashMap = linkedHashMaps.get(index);
            //车牌号
            String plateNo = linkedHashMap.get("0");
            //车主
            String userName;
            //手机号码
            String mobile;
            //地址
            String address;
            //备注信息
            String remark;
            //起始日期
            String startDate;
            //结束日期
            String endDate;
            //起始时间
            String startTime;
            //结束时间
            String endTime;

            BlackAndWhiteImportResult message = new BlackAndWhiteImportResult();
            message.setTotalCount(linkedHashMaps.size());
            message.setId(index + 3);
            message.setPlateNo(plateNo);
            message.setStatus("失败");

            if (StringUtils.isBlank(plateNo) || !PlateNoCheckUtil.checkPlateNo(plateNo)) {
                // 如果车辆的车牌号为空或错误的格式，放弃此数据，立即开始导入一下条数据
                log.error("车牌号格式错误");
                if (JddConstant.StringNumber.STRING_ONE.equals(isForever)) {
                    message.setUserName(linkedHashMap.get("2"));
                } else {
                    message.setUserName(linkedHashMap.get("6"));
                }
                message.setMessage("车牌号格式错误");
                resultList.add(message);
                continue;
            } else {
                parkBlackInfo.setPlateNo(plateNo);
            }

            //永久有效
            if (JddConstant.StringNumber.STRING_ONE.equals(isForever)) {
                userName = linkedHashMap.get("2");
                mobile = linkedHashMap.get("3");
                address = linkedHashMap.get("4");
                remark = linkedHashMap.get("5");
                message.setUserName(userName);
            } else {
                //自定义时间
                userName = linkedHashMap.get("6");
                mobile = linkedHashMap.get("7");
                address = linkedHashMap.get("8");
                remark = linkedHashMap.get("9");
                message.setUserName(userName);

                startDate = linkedHashMap.get("2");
                if (dateTimeCheck(startDate, "yyyy-MM-dd")) {
                    parkBlackInfo.setStartDate(DateUtil.fomatDate(startDate));
                } else {
                    log.error("起始日期格式错误");
                    message.setMessage("起始日期格式错误");
                    resultList.add(message);
                    continue;
                }
                endDate = linkedHashMap.get("3");
                if (dateTimeCheck(endDate, "yyyy-MM-dd")) {
                    parkBlackInfo.setEndDate(DateUtil.fomatDate(endDate));
                } else {
                    log.error("结束日期格式错误");
                    message.setMessage("结束日期格式错误");
                    resultList.add(message);
                    continue;
                }
                startTime = linkedHashMap.get("4");
                if (dateTimeCheck(startTime, "HH:mm:ss")) {
                    parkBlackInfo.setStartTime(DateUtil.fomatTime(startTime));
                } else {
                    log.error("开始时间格式错误");
                    message.setMessage("开始时间格式错误");
                    resultList.add(message);
                    continue;
                }
                endTime = linkedHashMap.get("5");
                if (dateTimeCheck(endTime, "HH:mm:ss")) {
                    parkBlackInfo.setEndTime(DateUtil.fomatTime(endTime));
                } else {
                    log.error("结束时间格式错误");
                    message.setMessage("结束时间格式错误");
                    resultList.add(message);
                    continue;
                }
//                parkBlackInfo.setWeekDay(weekDay);
            }

            if (StringUtils.isEmpty(userName) || userName.length() <= 40) {
                parkBlackInfo.setUserName(userName);
            } else {
                log.error("车主/姓名长度不要超过40个字符");
                message.setMessage("车主/姓名长度不要超过40个字符");
                resultList.add(message);
                continue;
            }

            if (StringUtils.isNotEmpty(mobile)) {
                if (BusinessUtils.isNumeric(mobile) && mobile.length() <= 15) {
                    parkBlackInfo.setMobile(mobile);
                } else {
                    log.error("手机号码格式不正确");
                    message.setMessage("手机号码格式不正确");
                    resultList.add(message);
                    continue;
                }
            }

            if (StringUtils.isEmpty(address) || address.length() <= 100) {
                parkBlackInfo.setAddress(address);
            } else {
                log.error("家庭住址长度不要超过100个字符");
                message.setMessage("家庭住址长度不要超过100个字符");
                resultList.add(message);
                continue;
            }

            if (StringUtils.isEmpty(remark) || remark.length() <= 100) {
                parkBlackInfo.setRemark(remark);
            } else {
                log.error("车辆备注长度不要超过100个字符");
                message.setMessage("车辆备注长度不要超过100个字符");
                resultList.add(message);
                continue;
            }

            parkBlackInfo.setId(SnowFlakeUtil.getId());
            parkBlackInfo.setIsForever(isForever);
            parkBlackInfo.setParkCode(configParkInfo.getParkCode());
            parkBlackInfo.setParkName(configParkInfo.getParkName());
            parkBlackInfo.setStatus("Y");
            parkBlackInfo.setLicenseType(Integer.parseInt(JddConstant.ParkWhiteListConstant.LICENSE_TYPE_TWO));
            parkBlackInfo.setUpdateTime(new Date());
            parkBlackInfo.setCreateUser(loginUser.getUsername());

            if (noSameDataPlantNoList.add(parkBlackInfo.getPlateNo())) {
                noSameDataList.add(parkBlackInfo);
            } else {
                message.setMessage("导入文件中已存在一条相同车牌号的数据，请勿重复导入");
                resultList.add(message);
                sameDatalist.add(parkBlackInfo);
            }
        }
        return resultList;
    }

    /**
     * 校验时间格式
     *
     * @param inputDateTime 时间字符串
     * @param format        时间格式
     * @return 校验结果
     */
    private boolean dateTimeCheck(String inputDateTime, String format) {
        SimpleDateFormat sdfDay = new SimpleDateFormat(format);
        sdfDay.setLenient(false);
        if (org.apache.commons.lang.StringUtils.isEmpty(inputDateTime)) {
            return false;
        }
        try {
            Date date = sdfDay.parse(inputDateTime);
            return inputDateTime.equals(sdfDay.format(date));
        } catch (ParseException e) {
            return false;
        }
    }

}
